/*
 * Copyright (c) 2016-2021, Hangzhou Qulian Technology Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "account.h"
#include "ecc.h"
#include "keccak256.h"
#include "contract.h"
#include "services.h"



#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <errno.h>

#define IOT_TEST
// #define NORMAL_TEST
// #define ETH_TEST
#ifdef ETH_TEST
#ifndef NORMAL_TEST
#undef ETH_TEST
#endif
#endif

#ifdef IOT_TEST
static const int port = 8080;

static int startSocketServer(void) {
    int tcpServerSockfd;
    struct sockaddr_in address; 
    memset(&address, 0, sizeof(address));
    /* create a TCP socket */ 
    if ((tcpServerSockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 
        printf("[Error] can not create socket\n"); 
        return -1; 
    } 
    /* bind to port 80 at any inteRFace */ 
    address.sin_family = AF_INET; 
    address.sin_port = htons(port); 
    address.sin_addr.s_addr = INADDR_ANY; 

    if (bind(tcpServerSockfd, (struct sockaddr *)&address, sizeof(address)) < 0) { 
        printf("[Error] can't bind socket\n"); 
        close(tcpServerSockfd); 
        return -1; 
    } 
    /* listen for connections (TCP listen backlog = 1) */ 
    listen(tcpServerSockfd, 5);
    return tcpServerSockfd;
}

static void alarmTask(char *sendMsg) {
    int clientSockfd;
    int len;
    struct sockaddr_in remotaAddr; //Server - side network address structure
    char buf[1024];  //Buffer for data transfer
    memset(&remotaAddr,0,sizeof(remotaAddr)); //Data initialization - clear zero
    remotaAddr.sin_family = AF_INET;  //Set it to IPV4 communication
    remotaAddr.sin_addr.s_addr = inet_addr("10.1.40.204");
    remotaAddr.sin_port = htons(80); //Server port number
    
    //Create client sockets --Ipv4, Connection-oriented communication, TCP
    //Returns 0 on success, -1 on failure
    if ((clientSockfd=socket(PF_INET, SOCK_STREAM, 0))<0) {
        printf("socket err\n");
        return ;
    }
    
    //Binds the socket to the server's network address
    if (connect(clientSockfd, (struct sockaddr *)&remotaAddr, sizeof(struct sockaddr))<0) {
        printf("connect err\n");
        return ;
    }
    memset(buf, 0, sizeof(buf));
    sprintf(buf, "%s", sendMsg);
    printf("send msg |%s| to alarm\n", buf);
    len=send(clientSockfd,buf,strlen(buf),0);
    if(len < 0)printf("socket send err\n");
    close(clientSockfd);
}

//send tx and receive receive
static char* url_handler(char* buf) {
    printf("recv:\n%s----------\n", buf);
    ql_strings_t *Post_Body = CreateStringsT();
    Post_Body->val = StrMalloc(buf, strlen(buf));
    Post_Body->len = strlen(buf);
    ql_strings_t *recv = NULL;
    sendToBlockchain("8.136.20.47:8081", Post_Body, &recv);
    FreeStringsT(Post_Body);
    if(recv == NULL || recv->val == NULL) {
        printf("recv nothing from hyperchain\n");
        FreeStringsT(recv);
        return NULL;
    }
    char *recv_buf = StrMalloc(recv->val, recv->len);
    FreeStringsT(recv);
    printf("recv from hyperchain:%s\n", recv_buf);
    return recv_buf;
}

void qlInit(account_t * my_account, abi_t *abiroot) {
    ql_byte_t acc_json[] = "{\"address\":\"8399b2b7e104cebb8b8938a2c79e26cb4733b0b5\",\"algo\":\"0x03\",\"version\":\"4.0\",\"publicKey\":\"049c660da3c16fd0df820b747d82344916db69d7553d2456323c820f1b1f4f225986d1f16cde06d99d94aa8998f0a14b6aeca21d7cad7670516cc911e4b035f9e5\",\"privateKey\":\"8747be107feb7959f4e8c8936a31aac5ffd4ed4d62d0e9edee2854531e62ea5e\"}";
    ql_err_t err = AccountInitJson(my_account, acc_json);
    if(err != ACCOUNT_SUCCESS) {
        printf("account_new failed : %d", err);
    }
    printf("account:%s\n", my_account->addr);
    char buf[] = "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"info\",\"type\":\"string\"}],\"name\":\"AlarmEvent\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_data\",\"type\":\"uint256\"}],\"name\":\"setThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"h\",\"type\":\"uint256\"}],\"name\":\"uploadInfo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]";
    err = AbiInitFromString(abiroot, buf);
    if(err != CONTRACT_SUCCESS)printf("abi init err\n");
    else printf("abi succeed\n");
}


//return -1  err
//return 0   nothing
//return 1   alarm
int getAlarm(char *Msg) {
    basic_response_t brp;//need init and clean
    cJSON *txhash = NULL;//need cjson_delete
    ql_err_t err;
    char *receipt_s;//need free
    cJSON *result = NULL;//need cjson_delete
    ReceiptResponse_t receipt;//need init and clean
    //from Msg to txhash
    BasicRspInit(&brp);//init
    err = BasicRspFromString(&brp, &txhash, Msg); 
    if(err < 0) {
        printf("get alarm err\n");
        CleanBasicrsp(&brp);
        cJSON_Delete(txhash);
        return -1;
    }
    CleanBasicrsp(&brp);//free
    //from txhash to receipt
    printf("txhash:%s\n", txhash->valuestring);
    receipt_s = pollingReceipt("8.136.20.47:8081", txhash->valuestring);
    cJSON_Delete(txhash);//free
    if(receipt_s != NULL) {
        printf("receipt:\n%s\n", receipt_s);
    } else {
        printf("no receipt\n");
        return -1;
    }
    //parse from receipt
    BasicRspInit(&brp);
    err = BasicRspFromString(&brp, &result, receipt_s);
    free(receipt_s);
    if(err < 0 || brp.code < 0 || result == NULL) {
        printf("parse err\n");
        CleanBasicrsp(&brp);
        cJSON_Delete(result);
        return -1;
    }
    CleanBasicrsp(&brp);
    ReceiptInit(&receipt);
    err = ReceiptFromJson(&receipt, result);
    cJSON_Delete(result);
    if(err < 0) {
        printf("get receipt from json err\n");
        return -1;
    }
    int ret = -1;
    if(receipt.log == NULL) {
        ret = 0;//nothing
    } else {
        ret = 1;
    }
    CleanReceipt(&receipt);
    return ret;
}
char* GetDeviceAddress(char *txString) {
    char* ret = NULL;
    cJSON *items = cJSON_Parse(txString);
    cJSON *params = cJSON_GetObjectItem(items, "params");
    cJSON *item = cJSON_GetArrayItem(params, 0);
    cJSON *from = cJSON_GetObjectItem(item, "from");
    if(from && from->valuestring)ret = StrMalloc(from->valuestring, strlen(from->valuestring));
    cJSON_Delete(items);
    return ret;
}


int main(int argc, const char * argv[]) {
    // blockchain
    account_t my_account;
    abi_t *abiroot = CreateAbi();
    qlInit(&my_account, abiroot);
    // socket
    int server_sockfd;
    int client_sockfd; //Client socket
    struct sockaddr_in remote_addr; //Client network address structure
    socklen_t sin_size;
    sin_size = sizeof(struct sockaddr_in);
    
    server_sockfd = startSocketServer();
    while(1) {
        sleep(2);
        if(server_sockfd <= 0) {
            printf("[Error] can not create socket\n"); 
            server_sockfd = startSocketServer();
            continue;
        }
        //等待客户端连接请求到达
        if ((client_sockfd=accept(server_sockfd, (struct sockaddr *)&remote_addr, &sin_size))<0) {
            perror("accept");
            close(client_sockfd);
            continue;
        }
        
        printf("accept client %s\n",inet_ntoa(remote_addr.sin_addr));
        
        unsigned char recv_buffer[1024]; 
        memset(recv_buffer, 0, sizeof(recv_buffer));
        
        /* Read in the request */ 
        int ret = read(client_sockfd, recv_buffer, 1024); 
        if (ret <= 0) { 
            close(client_sockfd); 
            printf("[Error] read failed\r\n"); 
            continue; 
        } 

        close(client_sockfd);

        char *deviceAddr = GetDeviceAddress(recv_buffer);
        char *hpc_msg = url_handler((char*)recv_buffer); 
        int isalarm= getAlarm(hpc_msg);
        free(hpc_msg);
        char alarmMsg[1024];

        if(isalarm)sprintf(alarmMsg, "{\"event\":\"alarm\", \"deviceAddress\":\"%s\"}", deviceAddr);
        else sprintf(alarmMsg, "{\"event\":\"notalarm\", \"deviceAddress\":\"%s\"}", deviceAddr);
        alarmTask(alarmMsg);
        free(deviceAddr);
    }

    close(server_sockfd);
    AbiFree(abiroot);
    return 0;
}
#endif

#ifdef NORMAL_TEST
void clean_strings(ql_strings_t* in) {
    in->len = 0;
    free(in->val);
    in->val = NULL;
    FreeStringsT(in->next);
    in->next = NULL;
}

int main() {
    ql_byte_t acc_json[] = "{\"address\":\"55a3c470f8cf73681cc6236801b5d65b3c673add\",\"algo\":\"0x03\",\"version\":\"4.0\",\"publicKey\":\"049c660da3c16fd0df820b747d82344916db69d7553d2456323c820f1b1f4f225986d1f16cde06d99d94aa8998f0a14b6aeca21d7cad7670516cc911e4b035f9e5\",\"privateKey\":\"bdb3962b58c23c9488743f8b6ba3bd2ef57025a939fc025820d25c09152dd99b\"}";
    // ql_byte_t acc_json[] = "{\"address\":\"8399b2b7e104cebb8b8938a2c79e26cb4733b0b5\",\"algo\":\"0x03\",\"version\":\"4.0\",\"publicKey\":\"049c660da3c16fd0df820b747d82344916db69d7553d2456323c820f1b1f4f225986d1f16cde06d99d94aa8998f0a14b6aeca21d7cad7670516cc911e4b035f9e5\",\"privateKey\":\"8747be107feb7959f4e8c8936a31aac5ffd4ed4d62d0e9edee2854531e62ea5e\"}";

    account_t my_account;
    tx_t tx;
    char* send_str;
    ql_strings_t* send_body;
    ql_strings_t *res;
    ql_err_t err;
    contract_t con;
    abi_t* abiroot;
    arg_t *args;
    basic_response_t basic_rsp;
    cJSON* result;
    char * tmp;
    ReceiptResponse_t deployReceipt;

    //create account
    err = AccountInitJson(&my_account, acc_json);
    if(err != ACCOUNT_SUCCESS) {
        printf("account_new failed : %d", err);
        return -1;
    }

#if 1
printf("\n----normal-tx-test----\n"); 
    err = TxSendNew(&tx, &my_account, my_account.addr, 122, NULL, "");
    if(err != ACCOUNT_SUCCESS) {
        printf("TxSendNew failed : %d", err);
        return -1;
    }  
    //get send str
    send_str = hpcAdapter("tx_sendTransaction", tx.from, tx.to, tx.value, NULL, tx.timestamp, tx.nonce, NULL, tx.extraid, tx.signature);
    printf("tx send_str:\n%s\n", send_str);

    //normal tx
    send_body = CreateStringsT();
    send_body->val = StrMalloc(send_str, strlen(send_str));
    send_body->len = strlen(send_str);
    sendToBlockchain("8.136.20.47:8081", send_body, &res);
    if(res != NULL)printf("recv\n%s\n", res->val);
    else printf("NULL\n");

    // mem free
    free(send_str);
    send_str = NULL;
    clean_strings(send_body);
    FreeStringsT(res);
    res = NULL;
 
    printf("-------------\n");
    printf("---deploy evm with param test---\n");
    char *payload = "608060405234801561001057600080fd5b50604051610e6d380380610e6d833981018060405281019080805182019291905050508060009080519060200190610049929190610050565b50506100f5565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061009157805160ff19168380011785556100bf565b828001600101855582156100bf579182015b828111156100be5782518255916020019190600101906100a3565b5b5090506100cc91906100d0565b5090565b6100f291905b808211156100ee5760008160009055506001016100d6565b5090565b90565b610d69806101046000396000f3006080604052600436106100f1576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305aca306146100f65780630b4e945d1461013d57806317d7de7c146101e4578063229bb9e9146102745780633fc70769146103565780634979abcc146103a057806354b8d5e3146104825780636a8c00bb146104cf57806389948ea01461055d5780639b88f8bd146105eb5780639c04c37214610679578063a566967e14610707578063b29ccd9414610795578063b447d16114610823578063cb153b24146108a6578063d59036fa146108e7578063ee1bd55114610975575b600080fd5b34801561010257600080fd5b506101236004803603810190808035151590602001909291905050506109c2565b604051808215151515815260200191505060405180910390f35b34801561014957600080fd5b5061018a60048036038101908080357effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690602001909291905050506109cc565b60405180827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b3480156101f057600080fd5b506101f96109d6565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561023957808201518184015260208101905061021e565b50505050905090810190601f1680156102665780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561028057600080fd5b506102db600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610a78565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561031b578082015181840152602081019050610300565b50505050905090810190601f1680156103485780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561036257600080fd5b50610384600480360381019080803560ff169060200190929190505050610a82565b604051808260ff1660ff16815260200191505060405180910390f35b3480156103ac57600080fd5b50610407600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610a8c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561044757808201518184015260208101905061042c565b50505050905090810190601f1680156104745780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561048e57600080fd5b506104b16004803603810190808035600019169060200190929190505050610a96565b60405180826000191660001916815260200191505060405180910390f35b3480156104db57600080fd5b5061051f6004803603810190808060600190600380602002604051908101604052809291908260036020028082843782019150505050509192919290505050610aa0565b6040518082600360200280838360005b8381101561054a57808201518184015260208101905061052f565b5050505090500191505060405180910390f35b34801561056957600080fd5b506105ad6004803603810190808060400190600280602002604051908101604052809291908260026020028082843782019150505050509192919290505050610ab0565b6040518082600260200280838360005b838110156105d85780820151818401526020810190506105bd565b5050505090500191505060405180910390f35b3480156105f757600080fd5b5061063b6004803603810190808060600190600380602002604051908101604052809291908260036020028082843782019150505050509192919290505050610ac0565b6040518082600360200280838360005b8381101561066657808201518184015260208101905061064b565b5050505090500191505060405180910390f35b34801561068557600080fd5b506106c96004803603810190808060600190600380602002604051908101604052809291908260036020028082843782019150505050509192919290505050610ad0565b6040518082600360200280838360005b838110156106f45780820151818401526020810190506106d9565b5050505090500191505060405180910390f35b34801561071357600080fd5b506107576004803603810190808060600190600380602002604051908101604052809291908260036020028082843782019150505050509192919290505050610ae0565b6040518082600360200280838360005b83811015610782578082015181840152602081019050610767565b5050505090500191505060405180910390f35b3480156107a157600080fd5b506107e56004803603810190808060400190600280602002604051908101604052809291908260026020028082843782019150505050509192919290505050610af0565b6040518082600260200280838360005b838110156108105780820151818401526020810190506107f5565b5050505090500191505060405180910390f35b34801561082f57600080fd5b50610864600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b00565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108b257600080fd5b506108d160048036038101908080359060200190929190505050610b0a565b6040518082815260200191505060405180910390f35b3480156108f357600080fd5b506109376004803603810190808060600190600380602002604051908101604052809291908260036020028082843782019150505050509192919290505050610b14565b6040518082600360200280838360005b83811015610962578082015181840152602081019050610947565b5050505090500191505060405180910390f35b34801561098157600080fd5b506109a46004803603810190808035600019169060200190929190505050610b24565b60405180826000191660001916815260200191505060405180910390f35b6000819050919050565b6000819050919050565b606060008054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a6e5780601f10610a4357610100808354040283529160200191610a6e565b820191906000526020600020905b815481529060010190602001808311610a5157829003601f168201915b5050505050905090565b6060819050919050565b6000819050919050565b6060819050919050565b6000819050919050565b610aa8610c4a565b819050919050565b610ab8610c6d565b819050919050565b610ac8610c8f565b819050919050565b610ad8610cb2565b819050919050565b610ae8610cd5565b819050919050565b610af8610cf8565b819050919050565b6000819050919050565b6000819050919050565b610b1c610d1a565b819050919050565b600060405180807f68656c6c6f000000000000000000000000000000000000000000000000000000815250600501905060405180910390207fb3a92a95ccbe77cba4bcec71319267f32d57fe1f2c9cc8de470c17b52b4b723a60006040518080602001828103825283818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610c085780601f10610bdd57610100808354040283529160200191610c08565b820191906000526020600020905b815481529060010190602001808311610beb57829003601f168201915b50509250505060405180910390a27f34a286cd617cdbf745989ac7e8dab3f95e8bb2501bcc48d9b6534b73d055a89c60405160405180910390a1819050919050565b606060405190810160405280600390602082028038833980820191505090505090565b6040805190810160405280600290602082028038833980820191505090505090565b606060405190810160405280600390602082028038833980820191505090505090565b606060405190810160405280600390602082028038833980820191505090505090565b606060405190810160405280600390602082028038833980820191505090505090565b6040805190810160405280600290602082028038833980820191505090505090565b6060604051908101604052806003906020820280388339808201915050905050905600a165627a7a7230582018fa715c50d5636011bb9f8c9d32629a5746e03fd173b89ec841ab52933782700029";
    ContractInit(&con, my_account.addr, NULL, NULL);
    //read abi
    char buf[] = "[{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"bool\"}],\"name\":\"TestBool\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"bytes1\"}],\"name\":\"TestBytes1\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes1\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"bytes\"}],\"name\":\"TestBytes\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint8\"}],\"name\":\"TestUint\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"string\"}],\"name\":\"TestString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"bytes32\"}],\"name\":\"getName\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256[3]\"}],\"name\":\"TestUintArray\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256[3]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"bytes32[2]\"}],\"name\":\"TestBytes32Array\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[2]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint8[3]\"}],\"name\":\"TestUint8Array\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8[3]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"bool[3]\"}],\"name\":\"TestBoolArray\",\"outputs\":[{\"name\":\"\",\"type\":\"bool[3]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"int8[3]\"}],\"name\":\"TestInt8Array\",\"outputs\":[{\"name\":\"\",\"type\":\"int8[3]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"address[2]\"}],\"name\":\"TestAddressArray\",\"outputs\":[{\"name\":\"\",\"type\":\"address[2]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"address\"}],\"name\":\"TestAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"int256\"}],\"name\":\"TestInt\",\"outputs\":[{\"name\":\"\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"int256[3]\"}],\"name\":\"TestIntArray\",\"outputs\":[{\"name\":\"\",\"type\":\"int256[3]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"bytes32\"}],\"name\":\"TestBytes32\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"name1\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"a\",\"type\":\"bytes\"},{\"indexed\":true,\"name\":\"b\",\"type\":\"string\"}],\"name\":\"eventA\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"eventB\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"a\",\"type\":\"string\"}],\"name\":\"eventB\",\"type\":\"event\"}]";
    abiroot = CreateAbi();
    err = AbiInitFromString(abiroot, buf);
    if(err != CONTRACT_SUCCESS)printf("abi init err\n");
    else printf("abi succeed\n");
    args = CreateArg();
    err = AddBytesArg(args, "contract01", strlen("contract01"));
    if(err != CONTRACT_SUCCESS)printf("add args err\n");
    else printf("args succeed\n");
    err = DeployEvmWithParam(&con, abiroot, payload, args);
    if(err != CONTRACT_SUCCESS)printf("deploy err\n");
    SetSignature(&con, my_account);
    //send
    send_str = hpcAdapter("contract_deployContract", con.from, con.to, con.value, con.payload, con.timestamp, con.nonce, con.extra, con.extraid, con.signature);
    // printf("send_str:\n%s\n", send_str);
    send_body->val = StrMalloc(send_str, strlen(send_str));
    send_body->len = strlen(send_str);
    sendToBlockchain("8.136.20.47:8081", send_body, &res);
    if(res != NULL)printf("%s\n", res->val);
    else printf("NULL\n");
    //mem free
    CleanContract(&con);
    ArgFree(args);
    args = NULL;
    free(send_str);
    send_str = NULL;
    clean_strings(send_body);

    printf("-------------\n");
    printf("---get deploy receipt test----\n");
    BasicRspInit(&basic_rsp);
    BasicRspFromString(&basic_rsp, &result, res->val);//get txHash
    CleanBasicrsp(&basic_rsp);//no use and clean it
    if(result != NULL && result->type == cJSON_String)printf("result:%s\n", result->valuestring);
    else {
	    printf("result is NULL\n");
	    return -1;
    } 
    tmp = pollingReceipt("8.136.20.47:8081", result->valuestring);//get receipt string
    printf("receipt :%s\n", tmp);
    BasicRspInit(&basic_rsp);
    cJSON_Delete(result);//before use
    result = NULL;
    BasicRspFromString(&basic_rsp, &result, tmp);//get result
    CleanBasicrsp(&basic_rsp);//no use and clean it

    ReceiptInit(&deployReceipt);
    ReceiptFromJson(&deployReceipt, result);
    printf("conAddr:%s\n", deployReceipt.conAddr);

    // CleanReceipt(&deployReceipt);
    free(tmp);
    FreeStringsT(res);//mem free
    res = NULL;
    cJSON_Delete(result);
    result = NULL;

    printf("-------------\n");
    printf("----invoke--test----\n");
    args = CreateArg();
    AddBytesArg(args, "1", strlen("1"));
    err = ContractInit(&con, my_account.addr, "", "");
    if(err != CONTRACT_SUCCESS)printf("contract init err\n");
    InvokeEVM(&con, deployReceipt.conAddr, "TestBytes32(bytes32)", abiroot, args);
    err = SetSignature(&con, my_account);
    if(err != CONTRACT_SUCCESS)printf("signature err\n");
    send_str = hpcAdapter("contract_invokeContract", con.from, con.to, con.value, con.payload, con.timestamp, con.nonce, con.extra, con.extraid, con.signature);
    printf("send_str:\n%s\n", send_str);
    //send
    send_body->val = StrMalloc(send_str, strlen(send_str));
    send_body->len = strlen(send_str);
    sendToBlockchain("8.136.20.47:8081", send_body, &res);
    if(res != NULL)printf("recv:\n%s\n", res->val);
    else printf("NULL\n");
    
    //free mem
    ArgFree(args);
    args = NULL;
    CleanContract(&con);
    free(send_str);
    send_str = NULL;
    clean_strings(send_body);

    printf("----get invoke receipt----\n");  
    BasicRspInit(&basic_rsp);
    err = BasicRspFromString(&basic_rsp, &result, res->val);
    CleanBasicrsp(&basic_rsp);
    if(err < 0)printf("parse invoke ret err\n");
    tmp = pollingReceipt("8.136.20.47:8081", result->valuestring);//get receipt string
    printf("invoke receipt :%s\n", tmp);

    FreeStringsT(res);
    res = NULL;
    cJSON_Delete(result);
    result = NULL;

    printf("-------------\n");
    printf("----decode--ret--test----\n");   
    BasicRspInit(&basic_rsp);
    err = BasicRspFromString(&basic_rsp, &result, tmp);
    if(err != RESPONSE_SUCCESS)printf("parse invoke deployReceipt ret err\n");
    ReceiptResponse_t invokeReceipt;
    ReceiptInit(&invokeReceipt);
    err = ReceiptFromJson(&invokeReceipt, result);
    if(err != RESPONSE_SUCCESS)printf("parse result err in invokeReceipt\n");
    decode_t* decoderes = CreateDecodeT();
    err = DecodeRet(abiroot, "TestBytes32(bytes32)", invokeReceipt.ret, decoderes);
    if(err != RESPONSE_SUCCESS)printf("decode err\n");
    decode_t *ptr = decoderes;
    while(ptr) {
        printf("T:%d    len:%d\nval:", ptr->type, ptr->len);
        if(ptr->type == DEC_STRING)printf("%s\n", ptr->bytes);
        else for(int i = 0; i < ptr->len; i++) {
            if(ptr->type == DEC_BYTES)printf("%x ", ptr->bytes[i]);
            else printf("%llx ", *((ql_int64_t*)ptr->bytes + i));
        }
        ptr = ptr->next;
    }
    printf("\n");
    
    CleanBasicrsp(&basic_rsp);
    free(tmp);
    tmp = NULL;
    CleanReceipt(&invokeReceipt);
    cJSON_Delete(result);
    result = NULL;
    DecodeTFree(decoderes);

    CleanReceipt(&deployReceipt);
    AbiFree(abiroot);
    FreeStringsT(send_body);
#endif

#ifdef ETH_TEST
    printf("-------------\n");
    //eth test
    printf("----eth--test----\n");
    char abi_buf[] = "[\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"add\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"MyEvent\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"retrieve\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"num\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"store\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  }\n]\n";
    abiroot = CreateAbi();
    err = AbiInitFromString(abiroot, abi_buf);
    if(err < 0)printf("abi init from string err\n");

    err = ContractInit(&con, my_account.addr, "", "");
    if(err < 0)printf("con init err\n");
    args = CreateArg();
    // AddIntArg(args, 0xff);
    err = InvokeEVM(&con, "0xEFB624b4ff269Bc6eED7B82ef16D5a9eB8B07a05", "retrieve()", abiroot, NULL);
    if(err < 0) printf("invoke evm err\n");
    // err = InvokeEVM(&con, "0xEFB624b4ff269Bc6eED7B82ef16D5a9eB8B07a05", "retrieve()", abiroot, NULL);

    send_str = ethAdapter(3, 0x8100, 0x59ec0, "0xEFB624b4ff269Bc6eED7B82ef16D5a9eB8B07a05", 0, con.payload, my_account.prikey);
    //tx
    // send_str = ethAdapter(0x1c, 0x2dc6c22, 0x30d41110, my_account.addr, 1, "0x", my_account.prikey);
    // send_str = ethAdapter(0x8000, 0x01, 0x02710000000, "0x0000000000000000000000000000000000000000", 0, "0x7f7465737432000000000000000000000000000000000000000000000000000000600057", my_account.prikey);
    printf("send_str:%s\n", send_str);
    frere(send_str);

    send_body = CreateStringsT();
    send_body->val = StrMalloc(send_str, strlen(send_str));
    send_body->len = strlen(send_str);
    res = NULL;
    sendToBlockchain("172.31.10.63:8545", send_body, &res);
    if(res != NULL)printf("%s\n", res->val);
    else printf("NULL\n");
    clean_strings(send_body);
    FreeStringsT(res);
    res = NULL;

    //deploy test
    printf("----eth-deploy-test----\n");
    send_str = ethAdapter(12, 0x01, 0x02710000000, ADDR_ZERO, 0, "0x7f7465737432000000000000000000000000000000000000000000000000000000600057", my_account.prikey);
    printf("eth_str:%s\n", send_str);
    send_body->val = StrMalloc(send_str, strlen(send_str));
    send_body->len = strlen(send_str);
    sendToBlockchain("172.31.10.63:8545", send_body, &res);
    if(res != NULL)printf("%s\n", res->val);
    else printf("NULL\n");

    AbiFree(abiroot);
    CleanContract(&con);
    ArgFree(args);
    FreeStringsT(send_body);
    FreeStringsT(res);
#endif
    return 0;
}

#endif
